﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Gmantis.Controls.Chart
{
    public enum BorderStyle
    {
        Light,
        Dark,
        Combo
    }

    public class BorderEffect : VisualEffect
    {
        // Fields
        public static DependencyProperty BorderStyleProperty = DependencyProperty.Register("BorderStyle", typeof(BorderStyle), typeof(BorderEffect), new PropertyMetadata(BorderStyle.Light, new PropertyChangedCallback(VisualEffect.OnChanged)));
        public static DependencyProperty LightAngleProperty = DependencyProperty.Register("LightAngle", typeof(double), typeof(BorderEffect), new PropertyMetadata(45.0, new PropertyChangedCallback(VisualEffect.OnChanged)));
        public static DependencyProperty ThicknessProperty = DependencyProperty.Register("Thickness", typeof(double), typeof(BorderEffect), new PropertyMetadata(10.0, new PropertyChangedCallback(VisualEffect.OnChanged)));

        // Methods
        private static Canvas CreateBorder(Geometry g, BorderStyle style, Brush brush1, Brush brush2, double size, double angle)
        {
            Canvas canvas = new Canvas
            {
                UseLayoutRounding = false,
                Clip = VfxTools.CloneGeometry(g)
            };
            double opacity = 0.0;
            for (int i = 0; i < size; i++)
            {
                double num3 = (i + 1.0) / size;
                if (opacity != 0.0)
                {
                    opacity = num3 - opacity;
                }
                else
                {
                    opacity = num3;
                }
                if (style != BorderStyle.Dark)
                {
                    Path path = CreatePath(g, brush1, (2.0 * (size - i)) - 1.0, opacity, angle, false);
                    canvas.Children.Add(path);
                }
                if (style != BorderStyle.Light)
                {
                    Path path2 = CreatePath(g, brush2, (2.0 * (size - i)) - 1.0, opacity, angle, true);
                    canvas.Children.Add(path2);
                }
            }
            return canvas;
        }

        internal override UIElement CreateForegroundEffect(Shape shape)
        {
            if (shape != null)
            {
                Geometry g = base.GetGeometry(shape);
                if (g != null)
                {
                    Color? color = base.GetColor(shape.Fill);
                    if (color.HasValue)
                    {
                        UIElement element = CreateBorder(g, this.BorderStyle, new SolidColorBrush(ClrTools.Lighten(color.Value)), new SolidColorBrush(ClrTools.Darken(color.Value)), this.Thickness, this.LightAngle);
                        if (element != null)
                        {
                            element.IsHitTestVisible = false;
                            return element;
                        }
                    }
                }
            }
            return null;
        }

        private static Path CreatePath(Geometry g, Brush brush, double thickness, double opacity, double angle, bool reverse)
        {
            Path path = new Path
            {
                Stroke = brush,
                StrokeThickness = thickness,
                StrokeLineJoin = PenLineJoin.Round,
                StrokeStartLineCap = PenLineCap.Round,
                StrokeEndLineCap = PenLineCap.Round,
                Opacity = opacity
            };
            path.Data = VfxTools.CloneGeometry(g);
            Rect bounds = path.Data.Bounds;
            double width = bounds.Width;
            double height = bounds.Height;
            double num = 0.5;
            Point point = new Point(0.5, 0.5);
            if (!double.IsNaN(angle))
            {
                angle *= 0.017453292519943295;
                Point point2 = new Point(point.X + (num * Math.Cos(angle + 3.1415926535897931)), point.Y - (num * Math.Sin(angle + 3.1415926535897931)));
                Point point3 = new Point(point.X + (num * Math.Cos(angle)), point.Y - (num * Math.Sin(angle)));
                GradientStopCollection stops2 = new GradientStopCollection();
                GradientStop stop = new GradientStop
                {
                    Color = Colors.White,
                    Offset = reverse ? ((double)1) : ((double)0)
                };
                stops2.Add(stop);
                GradientStop stop2 = new GradientStop
                {
                    Color = Colors.Transparent,
                    Offset = reverse ? ((double)0) : ((double)1)
                };
                stops2.Add(stop2);
                GradientStopCollection gradientStopCollection = stops2;
                LinearGradientBrush brush2 = new LinearGradientBrush(gradientStopCollection, 0.0)
                {
                    StartPoint = point2,
                    EndPoint = point3
                };
                path.OpacityMask = brush2;
            }
            return path;
        }

        // Properties
        public BorderStyle BorderStyle
        {
            get
            {
                return (BorderStyle)base.GetValue(BorderStyleProperty);
            }
            set
            {
                base.SetValue(BorderStyleProperty, value);
            }
        }

        public double LightAngle
        {
            get
            {
                return (double)base.GetValue(LightAngleProperty);
            }
            set
            {
                base.SetValue(LightAngleProperty, value);
            }
        }

        public double Thickness
        {
            get
            {
                return (double)base.GetValue(ThicknessProperty);
            }
            set
            {
                base.SetValue(ThicknessProperty, value);
            }
        }
    }
}
